package com.example.cocos2d_example;

import java.util.ArrayList;
import java.util.Random;

import org.cocos2d.actions.instant.CCCallFuncN;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.config.ccMacros;
import org.cocos2d.events.CCTouchDispatcher;
import org.cocos2d.layers.CCColorLayer;
import org.cocos2d.layers.CCScene;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.nodes.CCLabel;
import org.cocos2d.nodes.CCNode;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.nodes.CCTextureCache;
import org.cocos2d.opengl.CCTexture2D;
import org.cocos2d.sound.SoundEngine;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;
import org.cocos2d.types.CGSize;
import org.cocos2d.types.ccColor3B;
import org.cocos2d.types.ccColor4B;
import org.jbox2d.collision.AABB;
import org.jbox2d.collision.shapes.EdgeChainDef;
import org.jbox2d.collision.shapes.PolygonDef;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.World;

import android.content.Context;
import android.util.Log;
import android.view.MotionEvent;

public class GameLayer extends CCColorLayer
{
	public static final int kTagSpriteManager = 1;
	
	// Pixel to meters ratio. Box2D uses meters as the unit for measurement.
	// This ratio defines how many pixels correspond to 1 Box2D "meter"
	// Box2D is optimized for objects of 1x1 meter therefore it makes sense
	// to define the ratio so that your most common object type is 1x1 meter.
    protected static final float PTM_RATIO = 32.0f;
    
    // Simulation space should be larger than window per Box2D recommendation.
    protected static final float BUFFER = 1.0f;
    
    protected World bxWorld;
	
    protected CCTexture2D tex2;
    
    
    /*
	public static CCScene scene()
	{
		CCScene scene = CCScene.node();
		CCColorLayer layer = new GameLayer(ccColor4B.ccc4(255, 255, 255, 255));
		
		scene.addChild(layer);
		
		return scene;
	}
	*/
    
	protected GameLayer()
	{
		//scene
		super(ccColor4B.ccc4(255, 255, 255, 255));
		
		this.setIsTouchEnabled(true);
		this.setIsAccelerometerEnabled(true);
		
		CGSize s = CCDirector.sharedDirector().winSize();
        float scaledWidth = s.width/PTM_RATIO;
        float scaledHeight = s.height/PTM_RATIO;
        
        Vec2 lower = new Vec2(-BUFFER, -BUFFER);
    	Vec2 upper = new Vec2(scaledWidth+BUFFER, scaledHeight+BUFFER);
    	Vec2 gravity = new Vec2(0.0f, -10.0f);
    	
    	//480 800
    	
    	bxWorld = new World(new AABB(lower, upper), gravity, true);
    	
    	// TODO: JBox2D debug drawing is a bit different now.  We could add debug drawing the old way, but looks like that is going away soon.
    	/*
    	GLESDebugDraw debugDraw = new GLESDebugDraw( PTM_RATIO );        	
        bxWorld.setDebugDraw(debugDraw);

        int flags = 0;
        flags |= DebugDraw.e_shapeBit;
        flags |= DebugDraw.e_jointBit;
        flags |= DebugDraw.e_aabbBit;
        flags |= DebugDraw.e_pairBit;
        flags |= DebugDraw.e_centerOfMassBit;
        debugDraw.setFlags(flags);
        */
    	
    	BodyDef bxGroundBodyDef = new BodyDef();
        bxGroundBodyDef.position.set(0.0f, 0.0f);
        
        Body bxGroundBody = bxWorld.createBody(bxGroundBodyDef);

        EdgeChainDef bxGroundOutsideEdgeDef = new EdgeChainDef();
        bxGroundOutsideEdgeDef.addVertex(new Vec2(0f,0f));
        bxGroundOutsideEdgeDef.addVertex(new Vec2(0f,scaledHeight));
        bxGroundOutsideEdgeDef.addVertex(new Vec2(scaledWidth,scaledHeight));
        bxGroundOutsideEdgeDef.addVertex(new Vec2(scaledWidth,0f));            
        bxGroundOutsideEdgeDef.addVertex(new Vec2(0f,0f));
        bxGroundBody.createShape(bxGroundOutsideEdgeDef);
        
        tex2 =CCTextureCache.sharedTextureCache().addImage("blocks.png");
        
        //CCSprite mgr =new CCSprite();
        //addChild(mgr,0,kTagSpriteManager);
        
        addNewSpriteWithCoords(CGPoint.ccp(s.width / 2.0f, s.height / 2.0f));
        
        CCLabel label = CCLabel.makeLabel("Tap screen", "DroidSans", 32);
        label.setPosition(s.width / 2f, s.height - 50f);
        label.setColor(new ccColor3B(0, 0, 255));
        addChild(label);
	}
	
	@Override
	public void onEnter() {
		// TODO Auto-generated method stub
		super.onEnter();
		// start ticking (for physics simulation)
		schedule("tick");
	}
	
	@Override
	public void onExit() {
		// TODO Auto-generated method stub
		super.onExit();

		// stop ticking (for physics simulation)			
		unschedule("tick");
	}
	
	private void addNewSpriteWithCoords(CGPoint pos) {
		//CCSprite mgr = (CCSprite) getChild(kTagSpriteManager);
    	// We have a 64x64 sprite sheet with 4 different 32x32 images.  The following code is
    	// just randomly picking one of the images
    	int idx = (ccMacros.CCRANDOM_0_1() > 0.5f ? 0:1);
    	int idy = (ccMacros.CCRANDOM_0_1() > 0.5f ? 0:1);
    	CCSprite sprite = CCSprite.sprite(tex2,CGRect.make(idx * 32f, idy * 32f, 32f, 32f));
    	addChild(sprite);
    	
    	sprite.setPosition(pos.x, pos.y);
        
    	// Define the dynamic body.
    	// Set up a 1m squared box in the physics world
    	BodyDef bxSpriteBodyDef = new BodyDef();
    	bxSpriteBodyDef.userData = sprite;
    	bxSpriteBodyDef.position.set(pos.x/PTM_RATIO, pos.y/PTM_RATIO);
    	bxSpriteBodyDef.linearDamping = 0.3f;
    	
    	// Define another box shape for our dynamic body.
    	PolygonDef bxSpritePolygonDef = new PolygonDef();
    	bxSpritePolygonDef.setAsBox(0.5f, 0.5f);
    	bxSpritePolygonDef.density = 1.0f;
    	bxSpritePolygonDef.friction = 0.3f;

    	synchronized (bxWorld) {
    		// Define the dynamic body fixture and set mass so it's dynamic.
    		Body bxSpriteBody = bxWorld.createBody(bxSpriteBodyDef);
    		bxSpriteBody.createShape(bxSpritePolygonDef);
    		bxSpriteBody.setMassFromShapes();
    	}
    }
	
	public synchronized void tick(float delta) {
    	// It is recommended that a fixed time step is used with Box2D for stability
    	// of the simulation, however, we are using a variable time step here.
    	// You need to make an informed choice, the following URL is useful
    	// http://gafferongames.com/game-physics/fix-your-timestep/
    	
    	// Instruct the world to perform a simulation step. It is
    	// generally best to keep the time step and iterations fixed.
    	synchronized (bxWorld) {
    		bxWorld.step(delta, 10);
    	}
        	
    	// Iterate over the bodies in the physics world
    	for (Body b = bxWorld.getBodyList(); b != null; b = b.getNext()) {
    		Object userData = b.getUserData();
    		
    		if (userData != null && userData instanceof CCSprite) {
    			// Synchronize the AtlasSprite position and rotation with the corresponding body
    			CCSprite sprite = (CCSprite)userData;
        		sprite.setPosition(b.getPosition().x * PTM_RATIO, b.getPosition().y * PTM_RATIO);
        		sprite.setRotation(-1.0f * ccMacros.CC_RADIANS_TO_DEGREES(b.getAngle()));
    		}	
    	}
    	
    }
	
	@Override
	public boolean ccTouchesBegan(MotionEvent event) {
		// TODO Auto-generated method stub
		CGPoint location = CCDirector.sharedDirector().convertToGL(CGPoint.make(event.getX(), event.getY()));
		addNewSpriteWithCoords(location);
		return CCTouchDispatcher.kEventHandled;
	}
	
	
	@Override
	public void ccAccelerometerChanged(float accelX, float accelY, float accelZ) {
		// TODO Auto-generated method stub
		Vec2 gravity = new Vec2( accelX * -2.00f, accelY * -2.00f );
		
		bxWorld.setGravity( gravity );
	}
}